home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
tjgold.zip
/
INSTALL.004
/
FGUSER11.TXT
< prev
next >
Wrap
Text File
|
1995-05-29
|
27KB
|
643 lines
Pull-Down Menus
"Bell, book, and candle shall not
drive me back, when gold and silver
becks me to come on."
King John, Shakespeare
Introduction
We are excited. The pull-down menu features offered in Gold
are the most flexible and easy to use in the market place. In this
chapter you will learn about the following features of Gold's
pull-down menus and status bars:
Multiple menu styles are supported, including traditional,
chiseled, and a Microsoft Windows look-alike.
Pull-down menus support keyboard, mouse and hotkey input.
Menus can be nested many levels deep.
Separators and grayed items can be easily incorporated.
Figure 11.1
A Pull-Down Menu
with a
Status Bar
The Architecture of a Pull-Down Menu
A pull-down menu is actually a collection of separate menus
bound together. There is always one menu bar in a pull-down menu,
even if there is only one item on the bar. The menu bar defines the
menu items which appear across the top of the pull-down menu, i.e.
the items which are visible even when the menu is inactive.
Each item on the menu bar usually has a pop-up menu item
defined. Any item in a pop-up menu can point to another pop-up menu
thereby providing multiple levels of sub-menus.
This scheme of combining a menu bar with several pop-up menus
to create a pull-down menu is illustrated in Figure 11.2.
Building a Pull-Down menu
Enough theory; let's create a menu. Creating a menu is like
baking a cake, all you need to do is follow the recipe:
Declare the menu variables
Construct a menu bar with at least one item.
Construct as many pop-up menus as you need.
Activate the menu when a menu key is pressed in the application.
Call a sub-routine based on the user's menu selection.
Creating Menu Variables
Every pull-down menu has one menu bar. The menu bar is defined
in a variable of type Bar. Additionally, there is one pop-up menu
for each menu bar which has related options. Each menu pop-up is
define in a variable of type PopUp.
The following declaration is extracted from DEMPLL2.PAS which
defines a pull-down menu with two items on the menu bar, and two
pop-up menus.
var
MainMenu: Bar;
FileMenu: PopUp;
OptionsMenu: PopUp;
Constructing the Menu Bar
A variable of type Bar defines the content of the menu bar. To
construct a menu bar, the menu bar must first be initialized with
the InitBar procedure, and then items are added to the menu bar
with the BarAddItem procedure. These two procedures are defined as
follows:
InitBar(var P: Bar);
Sets a menu bar to the default values. This procedure must be
called prior to calling BarAddItem. The procedure is passed the
menu bar variable that will be initialized.
BarAddItem(var M: Bar; Item:string; ID:integer; HK,AltHK:word;
Desc:string; PopUp:pointer);
Adds an item to the menu bar. The procedure is passed the menu
bar variable, the text of the menu bar entry, the ID that will be
returned when the user presses help or selects the menu item, two
hotkeys (discussed below), the long description, and finally a
pointer to a pop-menu variable (if a pop-up is to be displayed when
the menu bar item is selected).
Managing Hotkeys
There are many different ways that a user can make a choice
from a pull-down menu: using the cursor keys to select an item and
pressing Enter, using the mouse and double-clicking on the menu
item, or pressing a hotkey. Gold supports three different levels of
hotkey.
As defined above, BarAddItem accepts two hotkey arguments. The
first hotkey is the upper-case letter that can be pressed when the
menu bar is active and the pop-up menus are not displayed. (This
state occurs when you press F10 in the BP7 environment.) If you
press the appropriate letter, Gold will jump to the menu item which
was defined with that hotkey.
The second hotkey passed to BarAddItem defines an alternate
key which can be pressed whenever a pop-up is displayed (no matter
how nested). The de facto standard is to use an Alt-letter key
sequence for the second hotkey.
For example, the a menu item define as "File" might have the
letter F as the first hot key (70) and Alt-F as the second hotkey
(289).
To visibly indicate to the user which letter is the hotkey
letter, use the "~" character to instruct gold to highlight the
letter, e.g. '~F~ile'. This technique works for the menu bar items
as well as pop-up items.
The third type of hotkey is defined globally and is not
directly associated with a specific menu item. For example, in BP7,
the File Open menu item is the hotkey F2. To define these
additional hotkeys, use the procedure BarAddHK which is defined as
follows:
BarAddHK(var P: Bar; K:word; HotID:integer);
Defines a general hotkey. The procedure is passed the menu bar
variable, the hotkey, and the ID which will be returned when the
hotkey is pressed.
Example
Listed below is an extract from DEMPLL2.PAS which initializes
a two item menu bar and defines some extra hotkeys:
procedure DefineMainMenu;
{}
begin
InitBar(MainMenu);
BarAddItem(MainMenu,'~F~ile',100,70,289,
'File management commands (open, new,
etc).',@FileMenu);
BarAddItem(MainMenu,'~O~ptions',800,79,280,
'Set defaults for compiler, editor,
mouse, debugger, etc.',@OptionsMenu);
BarAddHK(MainMenu,317,102); {F3 - File Open}
BarAddHK(MainMenu,316,103); {F2 - File Save}
BarAddHK(MainMenu,301,110); {Alt-X - quit}
end; { DefineMainMenu }
Notice that the last argument on the File menu constructor is
@FileMenu. This informs Gold that the pop-up menu FileMenu should
be displayed when the user selects File from the main menu bar.
Similarly, the Options menu bar item will call the pop-up
OptionsMenu.
Constructing the Menu Pop-Ups
The process of constructing a pop-up menu is very similar to
the process just described for menu bars. A variable of type PopUp
defines the content of the pop-up menu. To construct a pop-up menu,
the menu must first be initialized with the InitPopUp procedure,
and then items are added to the menu with the PopUpAddItem
procedure. These two procedure are defined as follows:
InitPopup(var M:PopUp);
Sets a pop-up menu to the default values. This procedure must
be called prior to calling PopUpAddItem. The procedure is passed
the popup menu variable that is to be initialized.
PopupAddItem(var P:PopUp;Item:string; ID:integer; HK:word;
Desc:string; ChildMenu:pointer);
Adds an item to the menu. The procedure is passed the pop-up
menu variable, the text of the menu item, the ID that will be
returned when the user presses help or selects the menu item, a
hotkey which can be used to select the item when the pop-up has
focus, the long description, and finally a pointer to another popup
variable if a pop-up is to be displayed when the menu item is
selected -- pass nil if there is no submenu.
Listed below is a PopupAddItem statement which defines the
"New " item on a file menu:
PopUpAddItem(FileMenu,'~N~ew',101,78,'Create a new file in a new
Edit window',nil);
Defining Separators, Grayed Items and Right Justified Text
By adding some reserved characters to the item text, you can
exert additional control over the item format.
Adding a Separator -- if the menu text is defined as a single
minus character "-", Gold will insert a menu separator instead of a
normal item. The other parameters are ignored, and can be set to
nulls. For example:
PopUpAddItem(FileMenu,'-',0,0,'',nil);
Graying an Item -- later you will read about the SetActive
procedures for making items grayed or selectable. An easy way to
make a menu item non-selectable is to insert the exclamation
character "!" in the first character of the item text. For example:
PopUpAddItem(EditMenu,'!~R~edo',202,82,'Redo the previously undone
editor operation',nil);
Right Justifying Text -- Traditionally, global hotkeys are
displayed right justified in the text of the menu item. To save
you the chore of entering the correct number of spaces to right
justify the hot key description, simply insert a colon ":" in the
item text. All characters to the right of the colon will be right
justified.
PopUpAddItem(FileMenu,'E~x~it:Alt-X',110,88,'~Exit~ Turbo
Pascal',nil);
Example
The following extract from DEMPLL2.PAS illustrates all the
above techniques, and shows how a file menu might be defined:
procedure DefineFilePopUp;
{}
begin
InitPopUp(FileMenu);
PopUpAddItem(FileMenu,'~N~ew',101,78,'Create a new
file in a new Edit window',nil);
PopUpAddItem(FileMenu,'~O~pen...:F3',102,79,'Locate
and open in an Edit window',nil);
PopUpAddItem(FileMenu,'~S~ave:F2',103,83,'Save the
file in the active Edit window',nil);
PopUpAddItem(FileMenu,'Save ~a~s...',104,65,'Save
the current file under a different name
directory or drive',nil);
PopUpAddItem(FileMenu,'Save a~l~l',105,76,'Save all
modified files',nil);
PopUpAddItem(FileMenu,'-',0,0,'',nil); {separator}
PopUpAddItem(FileMenu,'~C~hange dir...',106,67,
'Choose a new default directory',nil);
PopUpAddItem(FileMenu,'~P~rint',107,80,'Print the co
ntents of the active Edit window',nil);
PopUpAddItem(FileMenu,'P~r~inter setup',108,82, 'Choose printer filter to
use for printing',nil);
PopUpAddItem(FileMenu,'~D~os shell',109,68,
'Temporily exit to DOS',nil);
PopUpAddItem(FileMenu,'E~x~it:Alt-X',110,88,'~Exit~
Turbo Pascal',nil);
end; { DefineFilePopUp }
Look at the demo files DEMPLL1.PAS through DEMPLL4.PAS to see
more examples of menu constructions.
Activating a Pull-Down Menu
The GOLDDESK unit provides a very powerful and flexible way of
managing input to an application using a "desktop" just like the
desktop used in BP7. If you have not used a desktop, consider
reading the next chapter before deciding to roll-your-own desktop
using the primary menu input functions. You will probably find that
the desktop meets all of your needs (and then some).
Gold, however, does not force you to use the desktop. You can
always manage input to the application yourself and pass
menu-related keystrokes to the menu for processing. This section
describes how.
Invoking the Menu
The simplest way to pass control to the menu is to call the
function ActivatePullmenu. The function is passed the menu bar
variable and returns an integer indicating the users selection. For
example:
Choice := ActivatePullmenu(MainMenu);
If the user escaped from the menu without making a selection,
a zero is returned.
Passing keystrokes to the Menu
If a pull-down menu is to form the main task manager for an
application, the menu display functions should be placed inside a
loop that prompts the user to make a menu selection and then
responds to the selection (usually in the form of a case
statement).
The GOLDMENU unit includes the function IsPullkey which is
passed the menu variable along with Gold's standard three entries
which define a keystroke, i.e. the key, and the mouse X,Y
coordinates. The function returns true if the input should be
handled by the pull-down menu. When a true is returned, the
application should pass the keystroke to the menu using the
PullPushKey function -- this function simply instructs Gold to
process the passed keystroke rather than wait for new user input.
The following code fragment illustrates this basic technique:
with KeyVars do
repeat
GetInput;
if IsPullKey(MainMenu,LastKey,LastX,LastY) then
begin
Choice := PullPushKey(MainMenu,LastKey,LastX,
LastY);
case Choice of
101:;
102:;
103:;
........
end; {case}
end;
until Choice = 999;
The following example is an extract of DEMPLL3.PAS which uses
the plain ActivateMenu function if the user presses the slash key
or F10, and uses PullPushkey if the input is menu related.
DefineMenus;
DrawBar(MainMenu);
MouseShow(true);
CursorOff;
repeat
Choice := 0;
GetInput;
with KeyVars do
begin
if (LastKey = 47) {/}
or (LastKey = 324) {F10} then
Choice := ActivatePullMenu(mainmenu)
else if IsPullKey(MainMenu, LastKey, LastX, LastY) then
Choice := PullPushKey(MainMenu, LastKey, LastX,LastY);
case choice of
101:; {call the appropriate functions}
102:;
end;
if (Choice <> 0) and (Choice <> 110) then
PromptOK(' Gold ','You chose menu ID '+
IntToStr(Choice));
end;
until Choice = 110; {the exit choice}
MouseShow(false);
DisposeMenus;
Don't forget that the desktop can take care of all of this
input code for you. Further details are provided in the next
chapter.
Disposing of Menu Memory
The menu bar and the menu pop-ups use memory on the heap to
store the menu details. When a menu is no longer required, the menu
structures must be disposed of by calling DestroyBar and
DestroyPopup. The following code is taken from DEMPLL3.PAS:
procedure DisposeMenus;
{}
begin
DestroyBar(MainMenu);
DestroyPopUp(FileMenu);
DestroyPopUp(OptionsMenu);
DestroyPopUp(EnvironmentMenu);
end; { DisposeMenus }
Customizing the Menu's Appearance
Like many other Gold offerings, menus use industry standard
defaults to make it easy to create a professional and contemporary
application. However, various aspects of the menus can be
customized to meet individual tastes.
Customizing the Menu Style
The most dramatic way to change the overall menu appearance is
to change the menu style. The menu bar variable is actually a
record which contains a field named Style. The Style variable can
have any value in the range 1 to 4 as follows:
Style Description
1 A BP7-style menu with a single line border.
2 Similar to style 1, but the pop-up menu borders have a
chiseled affect. This is the default style.
3 This style takes advantage of Gold's custom characters,
and draws window borders along the outermost edge of
the pop-ups.
4 Draws a Microsoft Windows look-alike. This style can
take advantage of Gold's custom characters.
The default menu style is defined by the variable
MenuVars.PullStyle. -- its value is assigned to a menu bar when it
is initialized.
You can experiment with the menu styles by running DEMPLL4.PAS
and modifying the Mainmenu.Style value.
Customizing Menu Colors
You guessed it, you can customize any of the menu colors by
calling GoldSetColor. The following elements of TINT affect the
menu colors:
PullHiHot
PullHi
PullNormHot
PullNorm
PullOff
PullMsgHot
PullMsg
PullBorder1
PullBorder2
The following code is an extract from DEMCAL5.PAS which
customizes the menu colors:
procedure CustomizeColors;
{}
begin
GoldSetColor(PullHiHot,YellowOnBlue);
GoldSetColor(PullHi,WhiteOnBlue);
GoldSetColor(PullNormHot,YellowOnMagenta);
GoldSetColor(PullNorm,WhiteOnMagenta);
GoldSetColor(PullOff,LightgrayOnMagenta);
GoldSetColor(PullMsgHot,YellowonMagenta);
GoldSetColor(PullMsg,WhiteonMagenta);
GoldSetColor(PullBorder1,BlackOnmagenta);
GoldSetColor(PullBorder2,CyanOnMagenta);
end; { CustomizeColors }
Customizing Other Menu Components
A menu bar (record) variable contains additional fields
allowing you to customize the menu bar location, the long prompt
location, as well as optional characters used to designate special
items and highlight the active item.
Controlling the Menu Location
It is normal for the menu to occupy the top row of the screen
(or the top two rows for the Windows-style menu). However you can
position the menu where you want. The menu bar variables TopX and
TopY identify the location of the top left of the main menu bar.
When a menu bar is initialized, with InitBar, the values of TopX
and TopY are set to 1.
Controlling the Message Location
By default, the long description of the highlighted topic is
displayed at the bottom of the display. The message location can be
controlled by modifying the following fields of the menu bar
record: DescX1, DescX2 and DescY. These control the starting column
of the long description, the ending column of the long description,
and the row on which the description will be displayed.
If you are using a menu style of 4, the menu description
should be displayed on the top of the screen. The following extract
from DEMPLL4.PAS shows how to adjust the message location for
various styles:
if MainMenu.Style = 4 then
begin
ClearLine(1,WhiteOnBlue);
ClearLine(2,BlackOnLightgray);
MainMenu.DescX1 := 4;
MainMenu.DescX2 := 80;
MainMenu.DescY := 1;
GoldSetColor(PullMsgHot, whiteonblue);
GoldSetColor(PullMsg, lightgrayonblue);
end
Redefining Menu Display Characters
Earlier you learned that if the item text was a minus sign a
separator would be inserted in the pop-up. You also learned that an
item starting with an exclamation would be initially
non-selectable, and any text to the right of a colon would be right
justified.
These special characters are not hard coded, and can be
configured to use other characters. To change the characters,
simply assign new values to the following three variables:
MenuVars.Separator, MenuVars.InActiveChar and MenuVars.TabChar.
By assigning different characters to the variables
MenuVars.PullLeft and MenuVars.PullRight you can make the active
(or highlighted) item standout more clearly.
Finally, the character used to indicate that an item has a
sub-menu defaults to a right pointing chevron. You can use a
different character by assigning a new character value to the
MenuVars.PullSubIndicator variable.
Adding Menu Help
You can instruct Gold to call a custom help procedure to
provide menu context sensitive help. All you have to do is create a
procedure following some specific rules and call the procedure
AssignMenuHelpHook to instruct Gold to call your procedure every
time the user requests help while the menu has focus.
For a procedure to be eligible as a menu help hook it must
adhere to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to the section Understanding Hooks in chapter 3
for further information.
The procedure must be declared with one parameter of type
integer. This variable identifies the ID of the active item at
the time the user requested help.
The following procedure declaration follows these rules:
{$F+}
procedure MenuHelp(ID:integer);
{}
begin
PromptOK(' Help! ','You asked for help on item ID: '
+IntToStr(ID));
end; { MenuHelp }
{$F-}
The following procedure is then called to instruct Gold to
call your procedure after each input:
AssignMenuHelpHook(var M: Bar; Proc:PullHook);;
Instructs Gold to call the specified procedure when the user
requests help during menu selection.
When a help hook is implemented, Gold automatically adds a
help string to the long description line, i.e. at coordinates
(MenuVars.DescX1, MenuVars.MsgY). The user can click on this area
with the mouse, to access the help.
International users note that the actual text of the help
string is defined in the variable MenuVars.HelpStr and can be
modified as necessary. By default the help key is F1; this too can
be customized -- just assign an new keystroke value to the variable
MenuVars.HelpKey.
If, subsequently, you want to remove the help hook, call the
procedure RemoveMenuHelpHook.
The demo file DEMPLL4.PAS shows how a help hook can be added
to a pull-down menu.
Utilizing Menu Hind Hooks
If you want to write some additional information to the screen
based on the active menu item, you should take advantage of the
pull-down menu's hind hook. A hind hook is called once when the
menu is first displayed, and every time a keystroke or mouse click
is processed by the menu.
For a procedure to be eligible as a pull-down menu hind hook
it must adhere to the following rules:
The procedure must be declared as a far procedure at the root
level. Refer to the section Understanding Hooks in chapter 3
for further information.
The procedure must be declared with one parameter of type
integer. This variable identifies the ID of the active item.
Just like the help hook described above, the hind hook can be
assigned and removed using AssignMenuHindHook and
RemoveMenuHindHook, respectively.
Changing Menu Settings On-The-Fly
Typically, you will create a pull-down menu when the
application is started, and destroy the menu when the application
is closed. During the session, you can change the look and feel of
the menu (without having to destroy and rebuild the menu) by using
the following procedures:
BarSetActive(var M: Bar; ID:integer; On: boolean);
Makes a menu bar item active or inactive.
BarChangeItem(var M: Bar; ID:integer; Item,Desc:string;
HK,AltHK:word; NewID:integer; PopUp:pointer);
Redefines all the components of a menu bar item.
BarChangeText(var M: Bar; ID:integer; Item,Desc:string);
Redefines the short and long descriptions of a menu bar item.
BarDelItem(var M: Bar; ID:integer);
Removes an item from a menu bar.
BarDelHK(var P: Bar; K:word);
Removes a global hot key.
PopUpSetActive(var P:PopUp; ID:integer; On: boolean);
Makes a pop-up menu item active or inactive.
PopUpChangeItem(var P:PopUp; ID:integer; Item,Desc:string;HK:word;
NewID:integer; ChildMenu:pointer);
Redefines all the components of a pop-up menu item.
PopUpChangeText(var P:PopUp; ID:integer; Item,Desc:string);
Redefines the short and long descriptions of a pop-up menu
item.
PopUpDelItem(var P:PopUp; ID:integer);
Removes an item from a pop-up menu.
Managing Status Bars
The good news is that you already know how to create a status
bar. A Status bar is actually a menu bar positioned at the bottom
of the screen. You'll learn more about status bars in the next
chapter.
Error Management
The pull down menu structures allocate memory on the heap and
so have the potential to fail. For example, there may be
insufficient free memory to add a menu bar or pop-up item. After
calling the BarAddItem and PopupAddItem procedures be sure to call
the function LastMenuError to see if the item addition was
successful.